package com.java.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.java.exceptioin.Assert;
import com.java.exceptioin.SrbException;
import com.java.mapper.UserAccountMapper;
import com.java.mapper.UserLoginRecordMapper;
import com.java.pojo.entity.UserAccount;
import com.java.pojo.entity.UserInfo;
import com.java.mapper.UserInfoMapper;
import com.java.pojo.entity.UserLoginRecord;
import com.java.pojo.vo.*;
import com.java.result.ResponseEnum;
import com.java.result.ResultCodeEnum;
import com.java.service.UserInfoService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.java.service.UserLoginRecordService;
import com.java.utils.JwtUtils;
import com.java.utils.MD5;
import com.java.utils.RegexValidateUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;

/**
 * <p>
 * 用户基本信息 服务实现类
 * </p>
 *
 * @author Helen
 * @since 2021-07-08
 */
@Service
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService {

    @Resource
    private UserInfoMapper userInfoMapper;

    @Resource
    private UserAccountMapper userAccountMapper;

    @Resource
    private UserLoginRecordMapper userLoginRecordMapper;

    @Resource
    private RedisTemplate redisTemplate;


    @Transactional(rollbackFor = {Exception.class})
    @Override
    public void register(RegisterVo registerVo) {
        //判断手机号是否为空
        String mobile = registerVo.getMobile();
        String code = registerVo.getCode();
        String password = registerVo.getPassword();
        Assert.notNull(mobile, ResponseEnum.MOBILE_NULL_ERROR);
        Assert.notNull(password, ResponseEnum.PASSWORD_NULL_ERROR);
        Assert.notNull(code, ResponseEnum.CODE_NULL_ERROR);
        boolean cellphone = RegexValidateUtils.checkCellphone(mobile);
        Assert.isTrue(cellphone,ResponseEnum.MOBILE_ERROR);

        String codeGen = (String)redisTemplate.opsForValue().get("srb:sms:code:" + mobile);
        //校验验证码
        Assert.equals(codeGen,code, ResponseEnum.CODE_ERROR);

        QueryWrapper<UserInfo> wrapper = new QueryWrapper<>();
        wrapper.eq("mobile",mobile);
        Integer count = userInfoMapper.selectCount(wrapper);
        if(count>0){
            throw new SrbException(ResultCodeEnum.REGISTER_MOBLE_ERROR);
        }

        UserInfo userInfo = new UserInfo();
        userInfo.setUserType(registerVo.getUserType());
        userInfo.setName(registerVo.getMobile());
        userInfo.setNickName(registerVo.getMobile());
        userInfo.setHeadImg(userInfo.IMG_AVANTAR);//用户头像
        userInfo.setStatus(userInfo.STATUS_NORMAL);//用户状态
        userInfo.setMobile(registerVo.getMobile());
        userInfo.setPassword(MD5.encrypt(registerVo.getPassword()));
        //插入userinfo
        userInfoMapper.insert(userInfo);

        //插入userAccount
        UserAccount userAccount = new UserAccount();
        userAccount.setUserId(userInfo.getId());
        userAccountMapper.insert(userAccount);
    }

    @Transactional(rollbackFor = {Exception.class})
    @Override
    public UserInfoVo login(LoginVo loginVo,String ip) {
        String mobile = loginVo.getMobile();
        Integer userType = loginVo.getUserType();
        //判断用户名是否存在
        QueryWrapper<UserInfo> wrapper = new QueryWrapper<>();
        wrapper.eq("mobile",mobile)
                .eq("user_type",userType);
        UserInfo userInfo = userInfoMapper.selectOne(wrapper);
        Assert.notNull(userInfo,ResponseEnum.LOGIN_MOBILE_ERROR);

        //密码是否和数据库的一致
        String password = loginVo.getPassword();
        String encrypt = MD5.encrypt(password);
        Assert.equals(encrypt,userInfo.getPassword(),ResponseEnum.LOGIN_PASSWORD_ERROR);

        Assert.equals(UserInfo.VERIFY,loginVo.getVerify(),ResponseEnum.CODE_ERROR);

        //用户状态是否被禁用
        Assert.equals(userInfo.getStatus(), userInfo.STATUS_NORMAL,ResponseEnum.LOGIN_LOKED_ERROR);
        UserInfoVo userInfoVo = new UserInfoVo();
        userInfoVo.setUserType(userInfo.getUserType());
        userInfoVo.setName(userInfo.getName());
        userInfoVo.setNickName(userInfo.getNickName());
        userInfoVo.setHeadImg(userInfo.getHeadImg());
        userInfoVo.setMobile(userInfo.getMobile());
        String token = JwtUtils.createToken(userInfo.getId(), userInfo.getName());
        userInfoVo.setToken(token);


        //记录到日志
        UserLoginRecord userLoginRecord = new UserLoginRecord();
        userLoginRecord.setUserId(userInfo.getId());
        userLoginRecord.setIp(ip);
        userLoginRecordMapper.insert(userLoginRecord);

        return userInfoVo;
    }

    @Override
    public IPage<UserInfo> selectByPageList(Integer pageNum,Integer pageSize,UserInfoQueryVo userInfoQueryVo) {
        QueryWrapper<UserInfo> wrapper = new QueryWrapper<>();
        String mobile = userInfoQueryVo.getMobile();
        Integer userType = userInfoQueryVo.getUserType();
        Integer status = userInfoQueryVo.getStatus();
        Page<UserInfo> page = new Page<>(pageNum, pageSize);
        if(wrapper == null){
            return userInfoMapper.selectPage(page,null);
        }
        wrapper.eq(StringUtils.isNotBlank(mobile),"mobile",userInfoQueryVo.getMobile())
                .eq(userType != null,"user_type",userType)
                .eq(status != null , "status",status);

        IPage<UserInfo> pageInfo = userInfoMapper.selectPage(page,wrapper);
        return pageInfo;
    }

    @Override
    public void lock(Integer id) {
        QueryWrapper<UserInfo> wrapper = new QueryWrapper<>();
        wrapper.eq("id",id);
        UserInfo userInfo = userInfoMapper.selectOne(wrapper);
        if(userInfo.getStatus() == 1){
            userInfo.setStatus(0);
            userInfoMapper.updateById(userInfo);
        }else if(userInfo.getStatus() == 0){
            userInfo.setStatus(1);
            userInfoMapper.updateById(userInfo);
        }
    }

    @Override
    public Boolean ckPhone(String phone) {
        QueryWrapper<UserInfo> wrapper = new QueryWrapper<>();
        wrapper.eq("mobile",phone);
        Integer count = userInfoMapper.selectCount(wrapper);
        return count > 0;//true:手机号已存在 false:手机号不存在
    }

    //获取用户绑定状态
    @Override
    public Integer getBindStatus(Long userId) {
        UserInfo userInfo = userInfoMapper.selectById(userId);
        return userInfo.getBindStatus();
    }

    @Override
    public UserIndexVo getUserCenter(Long userId) {

        UserIndexVo userIndexVo = new UserIndexVo();
        //查询用户数据
        UserInfo userInfo = userInfoMapper.selectById(userId);
        userIndexVo.setUserId(userId);
        userIndexVo.setName(userInfo.getName());
        userIndexVo.setNickName(userInfo.getNickName());
        userIndexVo.setUserType(userInfo.getUserType());
        userIndexVo.setHeadImg(userInfo.getHeadImg());
        userIndexVo.setBindStatus(userInfo.getBindStatus());

        //查询账户数据
        QueryWrapper<UserAccount> accountWrapper = new QueryWrapper<>();
        accountWrapper.eq("user_id",userId);
        UserAccount userAccount = userAccountMapper.selectOne(accountWrapper);
        //可用金额
        userIndexVo.setAmount(userAccount.getAmount());
        //冻结金额
        userIndexVo.setFreezeAmount(userAccount.getFreezeAmount());
        //查询 user_login_record 最近一次登录的时间
        QueryWrapper<UserLoginRecord> recordWrapper = new QueryWrapper<>();
        recordWrapper.eq("user_id",userId)
                .orderByDesc("id")
                .last("limit 1");
        UserLoginRecord userLoginRecord = userLoginRecordMapper.selectOne(recordWrapper);
        userIndexVo.setLastLoginTime(userLoginRecord.getCreateTime());

        return userIndexVo;
    }

    @Override
    public String getMobileByBindCode(String bindCode) {
        QueryWrapper<UserInfo> wrapper = new QueryWrapper<>();
        wrapper.eq("bind_code",bindCode);
        UserInfo userInfo = userInfoMapper.selectOne(wrapper);
        return userInfo.getMobile();
    }


}
